package main.view;

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.ResourceBundle;
import javax.swing.AbstractAction;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JSeparator;
import javax.swing.JTextField;
import main.controller.GEDIVAController;
import main.model.DataModel;


/**
 * Frame to communicate with the user.
 * 
 * @author Yaqi Zhang
 */

public class GEDIVAFrame extends JFrame {

    private static final long serialVersionUID = 1L;
    private static final Dimension CANVAS_SIZE = new Dimension(1000, 600);
    private static final Dimension URL_WINDOW_SIZE = new Dimension(300, 100);
    private static final int UIL_FIELD_SIZE = 40;
    private final JFileChooser myChooser;
    private final ResourceBundle myResources;
    private Canvas myCanvas;
    private DataModel myDataModel;
    private final Map<String, ActionListener> myInputButtons;
    private final GEDIVAController myControl;

    /**
     * 
     * @param title of the company
     * @param language using to display
     * @param control 
     */
    public GEDIVAFrame (String title, String language, GEDIVAController control) {
        myControl = control;
        setTitle(title);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        myChooser = new JFileChooser(System.getProperties().getProperty(
                "user.dir"));

        myResources = ResourceBundle.getBundle("resources." + language);

        // register the buttons and actions corresponding to each button
        myInputButtons = new LinkedHashMap<String, ActionListener>();
        registerButtons();

        getContentPane().add(makeInput(), BorderLayout.SOUTH);
        getContentPane().add(makeDisplay(), BorderLayout.CENTER);
        makeMenus();

        pack();
        setVisible(true);
    }

    protected void makeMenus () {
        JMenuBar bar = new JMenuBar();
        bar.add(makeFileMenu());
        setJMenuBar(bar);
    }

    @SuppressWarnings("serial")
    protected JMenu makeFileMenu() {
        JMenu result = new JMenu(myResources.getString("FileMenu"));
        result.add(new AbstractAction(
                myResources.getString("OpenLocallyCommand")) {
            @Override
            public void actionPerformed (ActionEvent e) {
                int response = myChooser.showOpenDialog(null);
                if (response == JFileChooser.APPROVE_OPTION) {
                    myControl.loadModel(myChooser.getSelectedFile());
                }
            }
        });
        result.add(new AbstractAction(myResources.getString("URLWindowTitle")) {
            @Override
            public void actionPerformed (ActionEvent e) {
                createURLFrame();
            }

        });
        result.add(new AbstractAction(myResources.getString("SaveCommand")) {
            @Override
            public void actionPerformed (ActionEvent e) {
            }
        });
        result.add(new JSeparator());
        result.add(new AbstractAction(myResources.getString("QuitCommand")) {
            @Override
            public void actionPerformed (ActionEvent e) {
                // end program
                System.exit(0);
            }
        });
        return result;
    }

    private void createURLFrame () {
        JFrame urlWindow = new JFrame();
        urlWindow.setSize(URL_WINDOW_SIZE);
        setTitle(myResources.getString("OpenURLCommand"));
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        final JTextField TEXTFIELD = new JTextField(UIL_FIELD_SIZE);
        urlWindow.getContentPane().add(TEXTFIELD, BorderLayout.NORTH);
        JButton confirm = new JButton(myResources.getString("ConfirmCommand"));
        confirm.addMouseListener(new MouseAdapter() {
            @Override
            public void mouseClicked (MouseEvent e) {
                myControl.loadModel(TEXTFIELD.getText());
            }
        });
        urlWindow.getContentPane().add(confirm, BorderLayout.CENTER);
        urlWindow.setVisible(true);
    }

    private void registerButtons () {
        // Initialize all buttons and actions
        myInputButtons.put("BarChartCommand", new ButtonAction() {
            @Override
            public void behavior (ActionEvent e) {
                myCanvas.setVisualizer(new BarChart(myDataModel, CANVAS_SIZE));
            }
        });

        myInputButtons.put("LineGraphCommand", new ButtonAction() {
            @Override
            public void behavior (ActionEvent e) {
                myCanvas.setVisualizer(new LineGraph(myDataModel, CANVAS_SIZE));
            }
        });

        myInputButtons.put("ClearCommand", new ButtonAction() {
            @Override
            public void behavior (ActionEvent e) {
                myCanvas.clear();
            }
        });
    }

    protected JComponent makeInput () {
        JPanel result = new JPanel();
        for (String c : myInputButtons.keySet()) {
            makeButton(result, c);
        }
        return result;
    }

    protected void makeButton (JPanel result, String command) {
        JButton button = new JButton(myResources.getString(command));
        ActionListener action = myInputButtons.get(command);
        if (action != null) {
            button.addActionListener(action);
        }
        result.add(button);
    }

    protected Canvas makeDisplay () {
        // create with size in rows and columns
        myCanvas = new Canvas(CANVAS_SIZE);
        return myCanvas;
    }

    /**
     * 
     * @param message 
     */
    public void showError (String message) {
        JOptionPane.showMessageDialog(this, message, "Input Error",
                JOptionPane.ERROR_MESSAGE);
    }

    /**
     * 
     * @param dataModel 
     */
    public void setDataModel (DataModel dataModel) {
        myDataModel = dataModel;
        myCanvas.setVisualizerData(dataModel);
        myCanvas.repaint();
    }

    private abstract class ButtonAction implements ActionListener {

        @Override
        public void actionPerformed (ActionEvent e) {
            try {
                behavior(e);
            }
            catch (NullPointerException ex) {
                ex.printStackTrace();
            }
            finally {
                repaint();
            }
        }

        // Override this to get the behavior you want
        public abstract void behavior (ActionEvent e);
    }
}
